"""
电影票API模块 (原 MovieApis.py)
提供电影票识别、订单管理等功能
"""

import json
import time
import os
import requests
import hashlib
import random
from datetime import datetime
from dotenv import load_dotenv


class MovieAPI:
    """电影票API客户端"""
    
    def __init__(self):
        load_dotenv()
        
        # 根据DEBUG环境变量设置API基础URL
        debug_mode = os.getenv('DEBUG', 'False').lower() == 'true'
        self.base_url = 'https://dev.api.movie.lztc.cc/' if debug_mode else 'https://pro.api.movie.lztc.cc/'
        
        # 获取AppID和AppSecret
        self.app_id = os.getenv('AppID', '')
        self.app_secret = os.getenv('AppSecret', '')
        
        # token相关变量
        self.token = None
        self.token_expire_time = 0
        # 最近一次识别出来的电影数据缓存，用于下单参数补全
        self.last_movie_data = None
        
        print(f"DEBUG模式: {debug_mode}")
        print(f"API基础URL: {self.base_url}")
        print(f"AppID: {self.app_id}")
  
    def _generate_sign(self, timestamp):
        """生成签名: MD5(appId + timestamp + appSecret)"""
        sign_str = f"{self.app_id}{timestamp}{self.app_secret}"
        return hashlib.md5(sign_str.encode('utf-8')).hexdigest()

    def _build_headers(self, token=None):
        """统一构建请求头"""
        headers = {
            'accept': 'application/json',
            'accept-language': 'zh-CN,zh;q=0.9',
            'cache-control': 'no-cache',
            'content-type': 'application/json',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
        }
        if token:
            headers['Authorization'] = f'{token}'
        return headers
    
    def _get_token(self):
        """获取token"""
        current_time = int(time.time())
        if self.token and current_time < self.token_expire_time:
            return self.token
        
        timestamp = str(int(time.time()))
        sign = self._generate_sign(timestamp)
        
        data = {
            'appId': self.app_id,
            'timestamp': timestamp,
            'sign': sign
        }
        
        headers = {
            'accept': 'application/json',
            'content-type': 'application/json',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
        }
        
        try:
            response = requests.post(f"{self.base_url}api/movie/auth/token", 
                                   headers=headers, 
                                   json=data)
            response.raise_for_status()
            result = response.json()
            
            if result.get('code') == 200:
                self.token = result['data']['token']
                self.token_expire_time = current_time + result['data']['expires_in']
                print(f"Token获取成功，有效期至: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.token_expire_time))}")
                return self.token
            else:
                print(f"Token获取失败: {result.get('msg', '未知错误')}")
                return None
                
        except requests.exceptions.RequestException as e:
            print(f"Token获取请求失败: {e}")
            return None

    def _post_json(self, path, payload, use_auth=True, retry_on_401=True):
        """
        统一的 POST JSON 请求封装
        - 自动拼接 base_url + path
        - 可选携带 token 并在 401 时重试一次
        """
        token = None
        if use_auth:
            token = self._get_token()
            if not token:
                return {"code": 401, "msg": "Token获取失败"}

        headers = self._build_headers(token)
        url = f"{self.base_url}{path}"
        try:
            resp = requests.post(url, headers=headers, json=payload)
            resp.raise_for_status()
            result = resp.json()
            # API 层的 401
            if retry_on_401 and result.get('code') == 401 and use_auth:
                print("Token已过期，重新获取...")
                self.token = None
                self.token_expire_time = 0
                token = self._get_token()
                if not token:
                    return {"code": 401, "msg": "Token获取失败"}
                headers = self._build_headers(token)
                resp = requests.post(url, headers=headers, json=payload)
                resp.raise_for_status()
                result = resp.json()
            return result
        except requests.exceptions.RequestException as e:
            print(f"POST请求失败: {e}")
            return None

    def get_movies_info(self, image_url):
        """通过图片URL获取电影信息"""
        payload = {'imageUrl': image_url}
        result = self._post_json('api/AutoAgent/goofish/movie', payload, use_auth=True, retry_on_401=True)
        if result and result.get('code') == 200 and isinstance(result.get('data'), dict):
            self.last_movie_data = result.get('data')
        return result

    def movie_goofish_order_create(self, buyer_id, seller_id, goods_id, buyer_nickname, movie_data, img_url=None):
        """创建闲鱼订单"""
        seat_ids = movie_data.get('seat_ids') or movie_data.get('seatIds')
        payload = {
            'buyer_id': str(buyer_id),
            'seller_id': str(seller_id),
            'goods_id': str(goods_id),
            'buyer_nickname': str(buyer_nickname),
            'film_name': movie_data.get('film_name'),
            'film_id': movie_data.get('film_id'),
            'cinema_name': movie_data.get('cinema_name'),
            'cinema_id': movie_data.get('cinema_id'),
            'city_name': movie_data.get('city_name'),
            'district_name': movie_data.get('district_name'),
            'hall_name': movie_data.get('hall_name'),
            'show_time': movie_data.get('show_time'),
            'show_id': movie_data.get('show_id') or movie_data.get('showId'),
            'seat': movie_data.get('seat'),
            'seat_ids': seat_ids,
            'seat_num': movie_data.get('seat_num'),
            'seat_type': movie_data.get('seat_type'),
            'market_price': movie_data.get('market_price'),
            'market_price_single': movie_data.get('market_price_single'),
            'api_price': movie_data.get('api_price'),
            'api_price_single': movie_data.get('api_price_single'),
            'bidding_min_price': movie_data.get('bidding_min_price'),
            'bidding_max_price': movie_data.get('bidding_max_price'),
        }
        if img_url:
            payload['img_url'] = str(img_url)

        return self._post_json('api/AutoAgent/goofish/order/create', payload, use_auth=True, retry_on_401=True)

    def movie_goofish_order_info(self, buyer_id, seller_id, goods_id):
        """查询订单信息"""
        payload = {
            'buyer_id': str(buyer_id),
            'seller_id': str(seller_id),
            'goods_id': str(goods_id),
        }
        return self._post_json('api/AutoAgent/goofish/order/info', payload, use_auth=True, retry_on_401=True)

    def movie_goofish_order_list(self, page=1, page_size=30):
        """获取订单列表"""
        payload = {
            'page': int(page),
            'page_size': int(page_size)
        }
        return self._post_json('api/AutoAgent/goofish/order/list', payload, use_auth=True, retry_on_401=True)

    def movie_goofish_order_confirm(self, order_no):
        """确认订单发货"""
        payload = {'order_no': int(order_no)}
        return self._post_json('api/AutoAgent/goofish/order/confirm', payload, use_auth=True, retry_on_401=True)

    def movie_goofish_order_update(self, order_no, state):
        """更新订单状态"""
        payload = {
            'order_no': int(order_no),
            'state': int(state),
        }
        return self._post_json('api/AutoAgent/goofish/order/update', payload, use_auth=True, retry_on_401=True)

    def _generate_third_order_no(self):
        """生成 thirdOrderId：goofish-年月日时分秒 + 3位随机数"""
        now = datetime.now().strftime('%Y%m%d%H%M%S')
        rnd = random.randint(0, 999)
        return f"goofish-{now}{rnd:03d}"

    def create_movie_order(self, show_id=None, seat=None, seat_ids=None, phone=None, money=None,
                          notify_url=None, accept_change_seat=1, order_type=1, seat_type=1,
                          third_order_no=None, cached_data=None):
        """创建电影订单"""
        if cached_data is None:
            cached_data = self.last_movie_data or {}

        def pick(d, *keys):
            for k in keys:
                if d and k in d and d[k]:
                    return d[k]
            return None

        show_id = show_id or pick(cached_data, 'showId', 'show_id')
        seat = seat or pick(cached_data, 'seat')
        seat_ids = seat_ids or pick(cached_data, 'seat_ids', 'seat_ids')
        money = money if money is not None else pick(cached_data, 'api_price', 'market_price')
        notify_url = notify_url or os.getenv('NOTIFY_URL', None)
        if not notify_url:
            notify_url = 'https://dev.api.movie.lztc.cc/notify/wxPayOut'

        third_order_no = third_order_no or self._generate_third_order_no()

        missing = []
        if not show_id: missing.append('showId')
        if not seat: missing.append('seat')
        if not seat_ids: missing.append('seat_ids')
        if not phone: missing.append('phone')
        if money is None: missing.append('money')
        if not notify_url: missing.append('notifyUrl')
        if missing:
            return {"code": 400, "msg": f"缺少必要参数: {', '.join(missing)}"}

        payload = {
            'showId': show_id,
            'seat': seat,
            'seat_ids': seat_ids,
            'phone': phone,
            'money': int(money),
            'notifyUrl': notify_url,
            'acceptChangeSeat': int(accept_change_seat),
            'orderType': int(order_type),
            'seatType': int(seat_type),
            'thirdOrderId': third_order_no,
        }
        return self._post_json('api/movie/order', payload, use_auth=True, retry_on_401=True)

